

#include "Engine.hpp"
#include "GameWorld.hpp"
#include "RenderSystem.hpp"
#include "Camera.hpp"
#include "Transform.hpp"
#include "MathHelper.hpp"
#include "FirstPersonMoverSystem.hpp"

using namespace Nano;

class DummySystem : public GameSystem {
    
public:
    void Initialize() {
        AddComponent<Camera>();
    }
    
};

Component(Velocity)
    
public:
    Vector3 Velocity;
    
    void Reset() {
        Velocity = Vector3(0,-10,0);
    }
    
    void Clone(const class Velocity& source) {
        Velocity = source.Velocity;
    }
};

class VelocitySystem : public GameSystem {
public:
    void Initialize() {
        AddComponent<Transform>();
        AddComponent<Velocity>();
    }
    
    void Update(float dt) {
        for (ObjectCollection::const_iterator it = Objects().begin(); it!=Objects().end(); ++it) {
            GameObject* go = *it;
            go->GetComponent<Transform>()->Position += go->GetComponent<Velocity>()->Velocity * dt;
        }
    }
};

class Destroyer : public GameSystem {
public:
    void Initialize() {
        AddComponent<Transform>();
        AddComponent<Velocity>();
    }
    
    void Update(float dt) {
        for (ObjectCollection::const_iterator it = Objects().begin(); it!=Objects().end(); ++it) {
            GameObject* go = *it;
            if (go->GetComponent<Transform>()->Position().y<-20) {
                go->Remove();
            }
        }
    }
};

Component(Deformer)
    void Reset() {}
    void Clone(const Deformer& source) {}
};

class MeshDeformer : public GameSystem {
public:
    void Initialize() {
        AddComponent<Mesh>();
        AddComponent<Deformer>();
    }
    
    void Update(float dt) {
        
        
        for (ObjectCollection::const_iterator it = Objects().begin(); it!=Objects().end(); ++it) {
            GameObject* go = *it;
            
            Mesh* mesh = go->GetComponent<Mesh>();
            for (int i=0; i<mesh->Vertices().size(); i++) {
                mesh->Vertices()[i].Position += mesh->Vertices()[i].Position.Normalized() * dt * 0.1f;
            }
            
        }
    }
    
    
};


class Tester : public GameState {
    
    GameWorld world;
    RenderSystem* renderer;
    GameObject* camera;
    Texture texture;
    GameObject* cube;
    
    void Initialized() {
        
        world.CreateSystem<DummySystem>();
        renderer = world.CreateSystem<RenderSystem>();
        world.CreateSystem<VelocitySystem>();
        world.CreateSystem<Destroyer>();
        world.CreateSystem<MeshDeformer>();
        world.CreateSystem<FirstPersonMoverSystem>()->Input = &Input;
        
        camera = world.CreateObject();
        camera->AddComponent<Camera>()->Viewport = Viewport();
        camera->AddComponent<Transform>()->Position = Vector3(5,0,20);
        camera->AddComponent<FirstPersonMover>();
                      
        Input.TouchDown += event_handler(this, &Tester::TouchDown);
    }
    
    
    void Update(float dt) {
        static float rotation =0;
        rotation+= dt;
        
        world.Update(dt);
                
        cube->GetComponent<Transform>()->Rotation = Quaternion(rotation, Vector3(1,1,1).Normalized()) * Quaternion(rotation);
        cube->GetComponent<Transform>()->Position = Vector3(rotation * 0.5f,0,0);
    }
    
    void Render() {
        glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
		glClear( GL_COLOR_BUFFER_BIT  | GL_DEPTH_BUFFER_BIT);
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_CULL_FACE);
        renderer->Render();
    }
    
    void TouchDown(TouchEvent e) {
        GameObject* clone = cube->Clone();
        
        clone->GetComponent<Velocity>()->Velocity = Vector3(MathHelper::Random(-10, 10), -10, 0);
        
    }
};
/*
int main() {
    Engine e;
    e.Start<Tester>();
    return 0;
}
*/